/************************************************************************/
/* From youtube@The Cherno: https://thecherno.com/engine                */
/* github: https://github.com/TheCherno/Hazel                           */
/************************************************************************/
#pragma once

#include "Catentacle/Core/Base.h"
#include "Catentacle/Core/Log.h"
#include <filesystem>

#ifdef CT_ENABLE_ASSERTS

// Alteratively we could use the same "default" message for both "WITH_MSG" and "NO_MSG" and
// provide support for custom formatting by concatenating the formatting string instead of having the format inside the default message
#define CT_INTERNAL_ASSERT_IMPL(type, check, msg, ...) { if(!(check)) { CT##type##ERROR(msg, __VA_ARGS__); CT_DEBUGBREAK(); } }
#define CT_INTERNAL_ASSERT_WITH_MSG(type, check, ...) CT_INTERNAL_ASSERT_IMPL(type, check, "Assertion failed: {0}", __VA_ARGS__)
#define CT_INTERNAL_ASSERT_NO_MSG(type, check) CT_INTERNAL_ASSERT_IMPL(type, check, "Assertion '{0}' failed at {1}:{2}", CT_STRINGIFY_MACRO(check), std::filesystem::path(__FILE__).filename().string(), __LINE__)

#define CT_INTERNAL_ASSERT_GET_MACRO_NAME(arg1, arg2, macro, ...) macro
#define CT_INTERNAL_ASSERT_GET_MACRO(...) CT_EXPAND_MACRO( CT_INTERNAL_ASSERT_GET_MACRO_NAME(__VA_ARGS__, CT_INTERNAL_ASSERT_WITH_MSG, CT_INTERNAL_ASSERT_NO_MSG) )

// Currently accepts at least the condition and one additional parameter (the message) being optional
#define CT_ASSERT(...) CT_EXPAND_MACRO( CT_INTERNAL_ASSERT_GET_MACRO(__VA_ARGS__)(_, __VA_ARGS__) )
#define CT_CORE_ASSERT(...) CT_EXPAND_MACRO( CT_INTERNAL_ASSERT_GET_MACRO(__VA_ARGS__)(_CORE_, __VA_ARGS__) )
#else
#define CT_ASSERT(...)
#define CT_CORE_ASSERT(...)
#endif